package jmine.tec.hydra.domain.message;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import jmine.tec.hydra.api.HydraMessage;
import jmine.tec.hydra.api.HydraSpecification;
import jmine.tec.hydra.domain.HydraSystem;
import jmine.tec.hydra.domain.specification.HydraSpecificationImpl;
import jmine.tec.persist.annotation.Alias;
import jmine.tec.persist.annotation.Index;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

import bancosys.tec.component.Documentation;
import bancosys.tec.persist.bussobj.PersistableBusinessObject;
import bancosys.tec.persist.persister.annotation.NaturalKey;

/**
 * Representa uma conversação entre o cliente e o sistema externo, contendo todas as mensagens trocadas entre eles.
 * 
 * @author piercio
 */
@Entity
@Table(name = "HYDRA_CONVERSATION")
@Alias("HYDCON")
@SequenceGenerator(name = "SEQ_HYDCON", sequenceName = "SEQ_HYDCON")
@Documentation("ARMAZENA UMA CONVERSACAO COM UM SISTEMAS INTEGRADO E SUAS MENSAGENS.")
public class HydraConversation extends PersistableBusinessObject {

    private Long id;

    private String mnemonico;

    private HydraSpecification specification;

    private List<HydraMessage> messages;

    /**
     * @return o valor do id da conversa.
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_HYDCON")
    @Column(name = "COD_HYDRA_CONVERSATION", nullable = false)
    @Documentation("CODIGO DA CONVERSA.")
    public Long getId() {
        return this.id;
    }

    /**
     * @param id o valor do id da conversa.
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @return o valor do campo mnemonico
     */
    @NaturalKey
    @Column(name = "MNE_HYDRA_CONVERSATION", nullable = false)
    @Documentation("MENMONICO DA CONVERSA.")
    public String getMnemonico() {
        return this.mnemonico;
    }

    /**
     * @param mnemonico o valor para o campo mnemonico
     */
    public void setMnemonico(String mnemonico) {
        this.mnemonico = mnemonico;
    }

    /**
     * Devolve a especificação da conversa.
     * 
     * @return a especificação destino da conversa.
     */
    @Index(suffix = "JT_0")
    @ManyToOne(targetEntity = HydraSpecificationImpl.class)
    @JoinColumn(name = "COD_HYDRA_SPEC", nullable = false)
    @Documentation("CODIGO DA ESPECIFICAÇÃO.")
    public HydraSpecification getSpecification() {
        return this.specification;
    }

    /**
     * Define a especificação destino da conversa.
     * 
     * @param specification a especificação destino da conversa.
     */
    public void setSpecification(HydraSpecification specification) {
        this.specification = specification;
    }

    /**
     * @return sistema associado a especificação da conversa.
     */
    @Transient
    public HydraSystem getSystem() {
        return this.specification.getSystem();
    }

    /**
     * Devolve todas as mensagens trocadas nessa conversação.
     * 
     * @return todas as mensagens trocadas nessa conversação.
     */
    @Cascade(CascadeType.LOCK)
    @OneToMany(mappedBy = "conversation", targetEntity = HydraMessageImpl.class)
    @Documentation("MENSAGENS INTEGRANTES DA CONVERSA.")
    public List<HydraMessage> getMessages() {
        if (this.messages == null) {
            this.messages = new ArrayList<HydraMessage>();
        }
        return this.messages;
    }

    /**
     * Define as mensagens dessa conversação.
     * 
     * @param messages as mensagens dessa conversação.
     */
    public void setMessages(List<HydraMessage> messages) {
        this.messages = messages;
    }

    /**
     * Adiciona uma mensagem a conversação.
     * 
     * @param message a mensagem a ser adicionada.
     */
    public void addMessage(HydraMessage message) {
        message.setConversation(this);
        this.getMessages().add(message);
    }

    /**
     * Remove a mensagem informada da conversa.
     * 
     * @param message mensagem a ser removida.
     */
    public void removeMessage(HydraMessage message) {
        message.setConversation(null);
        this.getMessages().remove(message);
    }

    /**
     * @return numero de mensagens dessa conversa.
     */
    public int size() {
        return this.messages == null ? 0 : this.messages.size();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "Conversa id: " + this.id + "; mnemonico: " + this.mnemonico + ".";
    }
}
